package grails.company

import grails.converters.JSON
import grails.test.mixin.*
import grails.test.mixin.domain.DomainClassUnitTestMixin
import org.junit.*

/**
 * See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
 */
@TestFor(ProjectController)
@Mock([Organization, Department, Project])
class ProjectControllerTests {

    Department d
    Project p

    @Before
    void setUp() {
        def o = new Organization(title: 'ACME', description: 'desc').save()
        d = new Department(title: 'Cartoons', description: 'desc', organization: o).save()
        new Project(title: 'Toy story', description: 'desc1', department: d).save()
        p = new Project(title: 'Shrek', description: 'desc2', department: d).save()
        params.data = [:]
    }

    private void assertProject(def json, Project p) {
        assertNotNull json
        assertNotNull p
        assertNotNull p.department
        assertEquals(json.title, p.title)
        assertEquals(json.description, p.description)
        assertEquals(json.parentId, p.department.id)
    }

    private assertResponseSuccess(boolean success = true) {
        def json = JSON.parse(response.contentAsString)
        assertNotNull json
        assertEquals(json.success, success)
    }

    void testListEmpty() {
        Project.metaClass.static.list = {-> [] }

        controller.list()

        assertResponseSuccess(false)
    }

    void testListNonEmpty() {
        controller.list()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertProject(json.data[1], p)
    }

    void testViewNoIdSet() {
        controller.view()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertProject(json.data[1], p)
    }

    void testViewInvalidIdSet() {
        params.data.id = -1

        controller.view()

        assertResponseSuccess(false)
    }

    void testViewValidIdSet() {
        params.data.id = p.id

        controller.view()

        assertResponseSuccess()
        def json = JSON.parse(response.contentAsString)
        assertProject(json.data, p)
    }

    void testUpdateNoIdSet() {
        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateNoTitleSet() {
        params.data.id = p.id

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateInvalidIdSet() {
        params.data.id = -1

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateValidate() {
        Project.metaClass.validate = {-> false }
        params.data.id = p.id
        params.data.title = p.title

        controller.update()

        assertResponseSuccess(false)
    }

    void testUpdateValidSet() {
        params.data.id = p.id
        params.data.title = 'NewTitle'

        controller.update()

        assertResponseSuccess()
        assertNotNull Project.findByTitle('NewTitle')
    }

    void testDeleteNoIdSet() {
        controller.delete()

        assertResponseSuccess(false)
    }

    void testDeleteInvalidIdSet() {
        params.data.id = -1

        controller.delete()

        assertResponseSuccess(false)
    }

    void testDeleteValidIdSet() {
        params.data.id = Project.findByTitle('Toy story').id

        controller.delete()

        assertResponseSuccess()
        assertNull Project.findByTitle('Toy story');
    }

    void testCreateNoParentIdSet() {
        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateInvalidParentIdSet() {
        params.data.parentId = -1
        params.data.title = 'NewOrganizationTitle'

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateValidate() {
        Project.metaClass.validate = {-> false }
        params.data.parentId = d.id
        params.data.title = 'NewOrganizationTitle'

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateSave() {
        Project.metaClass.save = {-> false }
        params.data.title = 'NewOrganizationTitle'
        params.data.parentId = d.id

        controller.create()

        assertResponseSuccess(false)
    }

    void testCreateValid() {
        params.data.title = 'NewOrganizationTitle'
        params.data.description = 'NewDescription'
        params.data.parentId = d.id

        controller.create()

        assertResponseSuccess()
        def prj = Project.findByTitle(params.data.title)
        assertProject(params.data, prj)
        def json = JSON.parse(response.contentAsString)
        assertProject(json.data, prj)
        assertTrue d.projects.contains(prj)
    }
}
